﻿(function(exports) {
	$(document).ready(function() {

		/*
		 * Define the core module
		 *
		 */
		var AvifaunaCore = (function() {

			var firstQuiz = true,
				birds,
				currentBird,
				training,
				trainingSets;

			function init(birdsData, trainingSetsData) {
				birds = _.map(birdsData, function(birdData) {
					return new Bird(birdData);
				});
				trainingSets = trainingSetsData;

				AvifaunaDOMEventsHandler.init();
				AvifaunaDisplay.init();
				AvifaunaSound.init();
			}
			
			function backToMainMenu() {
				AvifaunaDisplay.onBackToMainMenu();
				AvifaunaSound.stopSound();
				training = null;
			};

			function beginTraining (trainingSet) {
				var birdSet;
				
				AvifaunaSound.stopSound();
				birdSet = getBirdSet(trainingSet);
				training = new Training(birdSet, trainingSet);
				
				updateScore();
				showNewBirdInTraining();
				AvifaunaDisplay.onBeginTraining();
			};
			
			function beginTrainingWithId(trainingSetId) {
				beginTraining(getTrainingSetById(trainingSetId));
			};
			
			var finishTraining = function() {
				AvifaunaSound.stopSound();
				updateScore();
				AvifaunaDisplay.onFinishTraining(training);
			};

			function getAvailableRiddleAnswers(bird, set) {
				var answers = _.clone(set);
				var birdIndex = answers.indexOf(bird);
				if(birdIndex == -1) {
					throw new Error("Bird not found in the given set!");
				}
				answers.splice(birdIndex, 1);
				while(answers.length >= AvifaunaConfig.maxAnswers) {
					answers.splice(Math.floor(Math.random() * answers.length), 1);
				}
				answers.push(bird);
				answers = _.shuffle(answers);
				return answers;
			};

			function getBirdById(id) {
				for(var i in birds) {
					if(birds[i].id === id) {
						return birds[i];
					}
				}
				return null;
			};

			function getBirdSet(trainingSet) {
				var set = [],
					bird;
					
				if(trainingSet.species.length == 0) {
					set = _.clone(birds);
				} else {
					trainingSet.species.forEach(function(id) {
						bird = getBirdById(id);
						if(bird == null) {
							throw new Error("Couldn't find bird set with id: " + id);
						}
						set.push(bird);
					});
				}
				return set;
			};

			function getTrainingSetById(id) {
				for(var i in trainingSets) {
					if(trainingSets[i].id === id) {
						return trainingSets[i];
					}
				}
				return null;
			};

			function isTimeForARiddle() {
				if(training.forceRiddle) {
					training.forceRiddle = false;
					return true;
				}
				if(training.holdRiddle) {
					training.holdRiddle = false;
					return false;
				}
				if((training.birdsIndex + 1) % 3 == 0) {
					return true;
				}
				return false;
			};
			
			function onNextBirdButtonClick() {
				if(training.birdsIndex == training.birdsShown.length - 1) {
					if(isTimeForARiddle()) {
						showNewBirdRiddleInTraining();
					} else {
						showNewBirdInTraining();
					}
				} else {
					showBird(training.birdsShown[++training.birdsIndex]);
				}
			}

			function onPreviousBirdButtonClick() {
				if(training.birdsIndex > 0) {
					showBird(training.birdsShown[--training.birdsIndex]);
				} else {
					training.birdsIndex = training.birdsShown.length - 1;
					showBird(training.birdsShown[training.birdsIndex]);
				}
			}

			function showBird(bird) {
				if(bird) {
					currentBird = bird;
					AvifaunaDisplay.showBird(bird);
				} else {
					throw new Error("No bird provided");
				}
			};

			function showBirdRiddle(bird, set) {
				if(bird) {
					riddleAnswers = getAvailableRiddleAnswers(bird, set);
					AvifaunaDisplay.showBirdRiddle(riddleAnswers, bird);
				} else {
					throw new Error("No bird provided");
				}
			};

			function showBirdWithId(birdId) {
				var bird = getBirdById(birdId);
				if(bird) {
					showBird(bird);
				} else {
					throw new Error("There is no entry with id: " + birdId);
				}
			};

			function showBirdWithIdRiddle(birdId, set) {
				var bird = getBirdById(birdId);
				if(bird) {
					showBirdRiddle(bird, set);
				} else {
					throw new Error("There is no entry with id: " + birdId);
				}
			};

			function showNewBirdInTraining() {
				var bird,
					birdPool,
					lastGuessedBirdIndex,
					lastShownBird,
					lastShownBirdIndex;
				
				AvifaunaDisplay.showVUMeter();
				training.birdsIndex++;
				if(training.birdsIndex < training.birds.length) {
					bird = training.birds[training.birdsIndex];
					training.uniqueBirdsShown.push(bird);
				} else {
					birdPool = _.clone(training.birdsNotGuessed);
					birdPool.push(training.birds[Math.floor(Math.random() * training.birds.length)]);
					lastGuessedBirdIndex = birdPool.indexOf(training.lastGuessedBird);
					if(lastGuessedBirdIndex !== -1) {
						birdPool.splice(lastGuessedBirdIndex, 1);
					}
					lastShownBird = training.birdsShown[training.birdsShown.length - 1];
					lastShownBirdIndex = birdPool.indexOf(lastShownBird);
					if(lastShownBirdIndex !== -1) {
						birdPool.splice(lastShownBirdIndex, 1);
					}
					bird = birdPool[Math.floor(Math.random() * birdPool.length)];
				}
				training.birdsShown.push(bird);
				showBird(bird);

				if(training.birdsIndex < AvifaunaConfig.tutorialTexts.length) {
					AvifaunaDisplay.updateTutorial(AvifaunaConfig.tutorialTexts[training.birdsIndex]);
				} else if(training.birdsIndex == AvifaunaConfig.tutorialTexts.length) {
					AvifaunaDisplay.hideTutorial();
				}

				AvifaunaDisplay.showPreviousBirdButton();
			};

			function showNewBirdRiddleInTraining() {
				var birdPool,
					lastBirdIndex;
				
				training.holdRiddle = true;
				if(training.uniqueBirdsShown.length == training.birds.length) {
					birdPool = _.clone(training.birdsNotGuessed);
					birdPool.push(training.birds[Math.floor(Math.random() * training.birds.length)]);
				} else {
					birdPool = _.clone(training.uniqueBirdsShown).splice(0, training.uniqueBirdsShown.length - 1);
				}
				lastBirdIndex = birdPool.indexOf(training.lastGuessedBird);
				if(lastBirdIndex !== -1) {
					birdPool.splice(lastBirdIndex, 1);
				}
				bird = birdPool[Math.floor(Math.random() * birdPool.length)];
				showBirdRiddle(bird, training.uniqueBirdsShown);
			};
			
			function submitRiddleSolution(riddleAnswer, rightAnswer) {
				var birdIndex;
				
				if($(riddleAnswer).hasClass("inactive")) {
					return;
				}
				
				if($(riddleAnswer).find("img").attr("data-avifauna-bird") === rightAnswer.id) { // Right answer
					AvifaunaDisplay.updateMainBirdPanelHeader("Zgadza się!");
					AvifaunaDisplay.updateTutorial('Doskonale! Postaraj się zapamiętać kolejne odgłosy równie uważnie...');
					birdIndex = training.birdsNotGuessed.indexOf(rightAnswer);
					if(birdIndex != -1) {
						training.birdsNotGuessed.splice(birdIndex, 1);
					}

					training.lastGuessedBird = rightAnswer;

					if(training.uniqueBirdsShown.length == training.birds.length) {
						training.forceRiddle = true;
					}

					if(training.birdsNotGuessed.length == 0) {
						finishTraining();
						return;
					}
				} else { // Wrong answer
					birdIndex = training.birdsNotGuessed.indexOf(rightAnswer);
					if(birdIndex === -1) {
						training.birdsNotGuessed.push(rightAnswer);
					}

					$("#mainBirdPanel h2").html("<span style='color: red'>Błędna odpowiedź.</span>");
					AvifaunaDisplay.updateTutorial('Nie przejmuj się, następnym razem będzie łatwiej!');
				}
				updateScore();
				AvifaunaDisplay.onSubmitRiddleSolution(riddleAnswer, rightAnswer);
			};
			
			var updateScore = function() {
				var guessed,
					total;
				
				guessed = training.birds.length - training.birdsNotGuessed.length;
				total = training.birds.length;
				AvifaunaDisplay.onUpdateScore(guessed, total);
			};

			return {
				init : init,
				beginTrainingWithId : beginTrainingWithId,
				backToMainMenu : backToMainMenu,
				onNextBirdButtonClick : onNextBirdButtonClick,
				onPreviousBirdButtonClick : onPreviousBirdButtonClick,
				submitRiddleSolution: submitRiddleSolution
			};

		})();

		exports.AvifaunaCore = AvifaunaCore;

	});
})(window);
